package com.bioscript.standalone;

import java.io.BufferedReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.w3c.dom.Document;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;

import com.bioscript.standalone.dataStructures.Range;
import com.bioscript.standalone.dataStructures.Snp;

public class UtilMethods {
	
	public static boolean writeXML(Document doc , String fileName)
	{
		try
		{
			DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
			DOMImplementationLS impl = 
				(DOMImplementationLS)registry.getDOMImplementation("LS");
			LSSerializer writer = impl.createLSSerializer();
			writer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
			LSOutput output = impl.createLSOutput();
			FileOutputStream fos = new FileOutputStream(new File(fileName));
			output.setByteStream(fos);
			System.out.println("impl == null " + impl == null);
			System.out.println("doc == null " + doc == null);
			System.out.println("fos == null " + fos == null);
			writer.write(doc, output);
			fos.close();
			return true;
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return false;
	}
	
	public static void checkFileAccess(String fileName)
	{
		if (fileName == null) 
			throw new NullPointerException(" provided fileName cannot be null");
		File fl = new File(fileName);
		if (!fl.exists() || !fl.isFile()) 
			throw new IllegalArgumentException(" file " + fileName + " does not exists or is not a file");
	}
	
	public static List<Snp> fetchDifferences(String[] filters, String fileName) throws Exception {
		Set<String> set = UtilMethods.fastaHeader(fileName,filters);
		List<Snp> diffs = new ArrayList<Snp>();
		for(String d : set)
		{
			String[] params = d.split("\t");
			Snp snp = new Snp(new Range(Integer.parseInt(params[1].trim()),
					Integer.parseInt(params[2].trim()),params[0].trim()));
			snp.setProperty(Snp.coverage, params[5].trim());
			snp.setProperty(Snp.fromChar, params[3].trim());
			snp.setProperty(Snp.tochar, params[4].trim());
			snp.setProperty(Snp.variants, params[6].trim());
			diffs.add(snp);
		}
		return diffs;
	}
	
	public static Set<String> fastaHeader(String geneFile, String[] filterStrings) throws Exception
	{
		TreeSet<String> geneSet = new TreeSet<String>();
		RandomAccessFile rand = new RandomAccessFile(geneFile, "r");
		String readLine = rand.readLine();
		while(readLine != null)
		{
			if (readLine.startsWith(">")) 
			{
				boolean consider = true;
				if (filterStrings != null)
				{
					for(String filterString : filterStrings)
					{
						if (readLine.contains(filterString))
						{
							consider = false;
							break;
						}
					}
				}
				if (consider)
				{
					readLine = readLine.substring(1);
					geneSet.add(readLine);
				}
			}
			readLine = rand.readLine();
		}
		rand.close();
		return geneSet;
	}
	
	public static void WriteToFile(List<? extends Range> list, String fileName, int field) throws IOException 
	{
		PrintWriter pw = new PrintWriter(new FileWriter(fileName));
		for (Range range : list)
		{
			switch(field)
			{
			case 1:
				pw.println(range.getLowerLimit() + "\t" + range.getUpperLimit());
				break;
			case 2:
				pw.println(range.getMetadata());
				break;
			case 3:
				pw.println(range.getLowerLimit() + "\t" + range.getUpperLimit() + "\t" + range.getMetadata());
				break;
			case 4:
				pw.println(range.getLowerLimit() + "\t" + range.getUpperLimit() + "\t" + range.getName());
				break;
			}
		}
		pw.flush();
		pw.close();
	}
	
	public static void copy (File src, File target) throws IOException
	{
		InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(target);
    
        // Transfer bytes from in to out
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) 
        {
            out.write(buf, 0, len);
        }
        in.close();
        out.close();
	}
	
	public static boolean cleanFolderRecursively(String folderName, boolean currentFolderToo) {
		try
		{
			File fl = new File(folderName);
			if (fl.exists() && fl.isDirectory())
			{
				File[] files = fl.listFiles();
				for (File file : files)
				{
					if (file.isDirectory())
					{
						if (cleanFolderRecursively(file.getAbsolutePath(),false))
						{
							if (!file.delete()) return false; 
						}
						else
							return false;
					}
					else
					{
						if (!file.delete()) return false;
					}
				}
				if (currentFolderToo)
				{
					return fl.delete();
				}
				return true;
			}
			else
			{
				System.out.append("Folder doesnt exist " + folderName);
				return true;
			}
		}
		catch(Exception e)
		{
			System.out.println("Problem deleting folder " + folderName);
			e.printStackTrace();
			return false;
		}
	}
	
	public static String reverseComplement(String str)
	{
		StringBuffer buffer = new StringBuffer();
		for (int i = str.length() - 1; i >= 0; i-- )
		{
			char ch = str.charAt(i);
			switch(ch)
			{
			case 'A' : ch = 'T';
						break;
			case 'a' : ch = 't';
						break;
			case 'C' : ch = 'G';
						break;
			case 'c' : ch = 'g';
					    break;
			case 'T' : ch = 'A';
						break;
			case 't' : ch = 'a';
						break;
			case 'G' : ch = 'C';
						break;
			case 'g' : ch = 'c';
						break;
			}
			buffer.append(ch);
		}
		return buffer.toString();
	}
	
	public static <K,V> HashMap<K,V> newHashMap()
	{
		return new HashMap<K, V>();
	}
	
	public static List<String> readTabDelimitedFile(String fileName, int columnNumber)
	{
		List<String> column = new ArrayList<String>();
		try
		{
			BufferedReader bufferedReader = new BufferedReader(new FileReader(fileName));
			String readLine = bufferedReader.readLine();
			while(readLine != null)
			{
				String[] params = readLine.split("\t");
				column.add(params[columnNumber].trim());
				readLine = bufferedReader.readLine();
			}
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return column;
	}
	
	public static int findGCContent(String str)
	{
		int result = 0 ;
		for (int i = 0 ; i < str.length(); i++)
		{
			char ch = str.charAt(i);
			if (ch == 'G' || ch == 'g' || ch == 'c' || ch == 'C')
			{
				result++;
			}
		}
		return result;
	}
}
